home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / misc / mtime.c < prev    next >
C/C++ Source or Header  |  2002-11-27  |  8KB  |  247 lines

  1. /*****************************************************************************
  2.  * mtime.c: high rezolution time management functions
  3.  * Functions are prototyped in mtime.h.
  4.  *****************************************************************************
  5.  * Copyright (C) 1998-2001 VideoLAN
  6.  * $Id: mtime.c,v 1.35 2002/11/11 14:39:12 sam Exp $
  7.  *
  8.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  * 
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24.  
  25. /*
  26.  * TODO:
  27.  *  see if using Linux real-time extensions is possible and profitable
  28.  */
  29.  
  30. /*****************************************************************************
  31.  * Preamble
  32.  *****************************************************************************/
  33. #include <stdio.h>                                              /* sprintf() */
  34.  
  35. #include <vlc/vlc.h>
  36.  
  37. #if defined( PTH_INIT_IN_PTH_H )                                  /* GNU Pth */
  38. #   include <pth.h>
  39. #endif
  40.  
  41. #ifdef HAVE_UNISTD_H
  42. #   include <unistd.h>                                           /* select() */
  43. #endif
  44.  
  45. #ifdef HAVE_KERNEL_OS_H
  46. #   include <kernel/OS.h>
  47. #endif
  48.  
  49. #if defined( WIN32 ) || defined( UNDER_CE )
  50. #   include <windows.h>
  51. #else
  52. #   include <sys/time.h>
  53. #endif
  54.  
  55. #if defined(HAVE_NANOSLEEP) && !defined(HAVE_STRUCT_TIMESPEC)
  56. struct timespec
  57. {
  58.     time_t  tv_sec;
  59.     int32_t tv_nsec;
  60. };
  61. #endif
  62.  
  63. #if defined(HAVE_NANOSLEEP) && !defined(HAVE_DECL_NANOSLEEP)
  64. int nanosleep(struct timespec *, struct timespec *);
  65. #endif
  66.  
  67. /*****************************************************************************
  68.  * mstrtime: return a date in a readable format
  69.  *****************************************************************************
  70.  * This functions is provided for any interface function which need to print a
  71.  * date. psz_buffer should be a buffer long enough to store the formatted
  72.  * date.
  73.  *****************************************************************************/
  74. char *mstrtime( char *psz_buffer, mtime_t date )
  75. {
  76.     static mtime_t ll1000 = 1000, ll60 = 60, ll24 = 24;
  77.  
  78.     sprintf( psz_buffer, "%02d:%02d:%02d-%03d.%03d",
  79.              (int) (date / (ll1000 * ll1000 * ll60 * ll60) % ll24),
  80.              (int) (date / (ll1000 * ll1000 * ll60) % ll60),
  81.              (int) (date / (ll1000 * ll1000) % ll60),
  82.              (int) (date / ll1000 % ll1000),
  83.              (int) (date % ll1000) );
  84.     return( psz_buffer );
  85. }
  86.  
  87. /*****************************************************************************
  88.  * mdate: return high precision date
  89.  *****************************************************************************
  90.  * Uses the gettimeofday() function when possible (1 MHz resolution) or the
  91.  * ftime() function (1 kHz resolution).
  92.  *****************************************************************************/
  93. mtime_t mdate( void )
  94. {
  95. #if defined( HAVE_KERNEL_OS_H )
  96.     return( real_time_clock_usecs() );
  97.  
  98. #elif defined( WIN32 ) || defined( UNDER_CE )
  99.     /* We don't get the real date, just the value of a high precision timer.
  100.      * this is because the usual time functions have at best only a milisecond
  101.      * resolution */
  102.     mtime_t freq, usec_time;
  103.  
  104.     if( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) )
  105.     {
  106.         /* Microsecond resolution */
  107.         QueryPerformanceCounter( (LARGE_INTEGER *)&usec_time );
  108.         return ( usec_time * 1000000 ) / freq;
  109.     }
  110.  
  111.     /* Milisecond resolution */
  112.     return 1000 * GetTickCount();
  113.  
  114. #else
  115.     struct timeval tv_date;
  116.  
  117.     /* gettimeofday() could return an error, and should be tested. However, the
  118.      * only possible error, according to 'man', is EFAULT, which can not happen
  119.      * here, since tv is a local variable. */
  120.     gettimeofday( &tv_date, NULL );
  121.     return( (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec );
  122.  
  123. #endif
  124. }
  125.  
  126. /*****************************************************************************
  127.  * mwait: wait for a date
  128.  *****************************************************************************
  129.  * This function uses select() and an system date function to wake up at a
  130.  * precise date. It should be used for process synchronization. If current date
  131.  * is posterior to wished date, the function returns immediately.
  132.  *****************************************************************************/
  133. void mwait( mtime_t date )
  134. {
  135. #if defined( HAVE_KERNEL_OS_H )
  136.     mtime_t delay;
  137.     
  138.     delay = date - real_time_clock_usecs();
  139.     if( delay <= 0 )
  140.     {
  141.         return;
  142.     }
  143.     snooze( delay );
  144.  
  145. #elif defined( WIN32 ) || defined( UNDER_CE )
  146.     mtime_t usec_time, delay;
  147.  
  148.     usec_time = mdate();
  149.     delay = date - usec_time;
  150.     if( delay <= 0 )
  151.     {
  152.         return;
  153.     }
  154.     msleep( delay );
  155.  
  156. #else
  157.  
  158.     struct timeval tv_date;
  159.     mtime_t        delay;          /* delay in msec, signed to detect errors */
  160.  
  161.     /* see mdate() about gettimeofday() possible errors */
  162.     gettimeofday( &tv_date, NULL );
  163.  
  164.     /* calculate delay and check if current date is before wished date */
  165.     delay = date - (mtime_t) tv_date.tv_sec * 1000000
  166.                  - (mtime_t) tv_date.tv_usec
  167.                  - 10000;
  168.  
  169.     /* Linux/i386 has a granularity of 10 ms. It's better to be in advance
  170.      * than to be late. */
  171.     if( delay <= 0 )                 /* wished date is now or already passed */
  172.     {
  173.         return;
  174.     }
  175.  
  176. #   if defined( PTH_INIT_IN_PTH_H )
  177.     pth_usleep( delay );
  178.  
  179. #   elif defined( ST_INIT_IN_ST_H )
  180.     st_usleep( delay );
  181.  
  182. #   else
  183.  
  184. #       if defined( HAVE_NANOSLEEP )
  185.     {
  186.         struct timespec ts_delay;
  187.         ts_delay.tv_sec = delay / 1000000;
  188.         ts_delay.tv_nsec = (delay % 1000000) * 1000;
  189.  
  190.         nanosleep( &ts_delay, NULL );
  191.     }
  192.  
  193. #       else
  194.     tv_date.tv_sec = delay / 1000000;
  195.     tv_date.tv_usec = delay % 1000000;
  196.     /* see msleep() about select() errors */
  197.     select( 0, NULL, NULL, NULL, &tv_date );
  198. #       endif
  199.  
  200. #   endif
  201.  
  202. #endif
  203. }
  204.  
  205. /*****************************************************************************
  206.  * msleep: more precise sleep()
  207.  *****************************************************************************
  208.  * Portable usleep() function.
  209.  *****************************************************************************/
  210. void msleep( mtime_t delay )
  211. {
  212. #if defined( HAVE_KERNEL_OS_H )
  213.     snooze( delay );
  214.  
  215. #elif defined( PTH_INIT_IN_PTH_H )
  216.     pth_usleep( delay );
  217.  
  218. #elif defined( ST_INIT_IN_ST_H )
  219.     st_usleep( delay );
  220.  
  221. #elif defined( WIN32 ) || defined( UNDER_CE )
  222.     Sleep( (int) (delay / 1000) );
  223.  
  224. #elif defined( HAVE_NANOSLEEP )
  225.     struct timespec ts_delay;
  226.  
  227.     ts_delay.tv_sec = delay / 1000000;
  228.     ts_delay.tv_nsec = (delay % 1000000) * 1000;
  229.  
  230.     nanosleep( &ts_delay, NULL );
  231.  
  232. #else
  233.     struct timeval tv_delay;
  234.  
  235.     tv_delay.tv_sec = delay / 1000000;
  236.     tv_delay.tv_usec = delay % 1000000;
  237.  
  238.     /* select() return value should be tested, since several possible errors
  239.      * can occur. However, they should only happen in very particular occasions
  240.      * (i.e. when a signal is sent to the thread, or when memory is full), and
  241.      * can be ignored. */
  242.     select( 0, NULL, NULL, NULL, &tv_delay );
  243.  
  244. #endif
  245. }
  246.  
  247.